package cc.sjfx.sharedoc.function;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.HashMap;

import cc.sjfx.sharedoc.R;
import cc.sjfx.sharedoc.utils.CheckUtils;

import com.bmob.BmobPro;
import com.bmob.BmobProFile;
import com.bmob.btp.callback.DownloadListener;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;

public class AsyncImageLoader {
	private HashMap<String, SoftReference<Bitmap>> imageCache;
	private Context context;
	private String path;

	public AsyncImageLoader(Context context) {
		imageCache = new HashMap<String, SoftReference<Bitmap>>();
		this.context = context;
		path = BmobPro.getInstance(context).getCacheDownloadDir();
	}

	public void loadDrawable(final String imageUrl,
			final ImageCallback imageCallback) {
		if(!CheckUtils.stringIsNull(imageUrl)){
			String icoPath = path + "/" + imageUrl;
			if (imageCache.containsKey(imageUrl)) {
				SoftReference<Bitmap> softReference = imageCache.get(imageUrl);
				Bitmap bitmap = softReference.get();
				if (bitmap != null) {
					imageCallback.imageLoaded(bitmap);
					return;
				} else {
					return;
				}
			}
			if (new File(icoPath).exists()) {
				Bitmap bitmap=BitmapFactory.decodeByteArray(decodeBitmap(icoPath), 0, decodeBitmap(icoPath).length);
				imageCache.put(imageUrl, new SoftReference<Bitmap>(bitmap));
				imageCallback.imageLoaded(bitmap);
			} else {
				downloadImage(imageUrl,imageCallback);
			}
		}else {
			Bitmap bitmap=BitmapFactory.decodeResource(context.getResources(), R.drawable.user_defaultico);
			imageCallback.imageLoaded(bitmap);
		}
	}

	private void downloadImage(final String imageUrl, final ImageCallback imageCallback) {
		// TODO Auto-generated method stub
		final Handler handler = new Handler() {
			@Override
			public void handleMessage(Message message) {
				imageCallback.imageLoaded((Bitmap) message.obj);
			}
		};
		BmobProFile.getInstance(context).download(imageUrl,
				new DownloadListener() {
					@Override
					public void onError(int arg0, String arg1) {
						// TODO Auto-generated method stub
					}
					@Override
					public void onSuccess(String arg0) {
//						Drawable drawable = Drawable.createFromPath(arg0);
						Bitmap bitmap=BitmapFactory.decodeByteArray(decodeBitmap(arg0), 0, decodeBitmap(arg0).length);
						imageCache.put(imageUrl,
								new SoftReference<Bitmap>(bitmap));
						Message message = handler
								.obtainMessage(0, bitmap);
						handler.sendMessage(message);
					}

					@Override
					public void onProgress(String arg0, int arg1) {
						// TODO Auto-generated method stub
					}
				});
	}
	private static byte[] decodeBitmap(String path) {  
        BitmapFactory.Options opts = new BitmapFactory.Options();  
        opts.inJustDecodeBounds = true;// 设置成了true,不占用内存，只获取bitmap宽高  
        BitmapFactory.decodeFile(path, opts);  
        opts.inSampleSize = computeSampleSize(opts, -1, 1024 * 800);  
        opts.inJustDecodeBounds = false;// 这里一定要将其设置回false，因为之前我们将其设置成了true  
        opts.inPurgeable = true;  
        opts.inInputShareable = true;  
        opts.inDither = false;  
        opts.inPurgeable = true;  
        opts.inTempStorage = new byte[16 * 1024];  
        FileInputStream is = null;  
        Bitmap bmp = null;  
        ByteArrayOutputStream baos = null;  
        try {  
            is = new FileInputStream(path);  
            bmp = BitmapFactory.decodeFileDescriptor(is.getFD(), null, opts);  
            double scale = getScaling(opts.outWidth * opts.outHeight,  
                    1024 * 600);  
            Bitmap bmp2 = Bitmap.createScaledBitmap(bmp,  
                    (int) (opts.outWidth * scale),  
                    (int) (opts.outHeight * scale), true);  
            bmp.recycle();  
            baos = new ByteArrayOutputStream();  
            bmp2.compress(Bitmap.CompressFormat.JPEG, 100, baos);  
            bmp2.recycle();  
            return baos.toByteArray();  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                is.close();  
                baos.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
            System.gc();  
        }  
        return baos.toByteArray();  
    }  
  
    private static double getScaling(int src, int des) {  
        /** 
         * 48 目标尺寸÷原尺寸 sqrt开方，得出宽高百分比 49 
         */  
        double scale = Math.sqrt((double) des / (double) src);  
        return scale;  
    }  
  
    public static int computeSampleSize(BitmapFactory.Options options,  
            int minSideLength, int maxNumOfPixels) {  
        int initialSize = computeInitialSampleSize(options, minSideLength,  
                maxNumOfPixels);  
  
        int roundedSize;  
        if (initialSize <= 8) {  
            roundedSize = 1;  
            while (roundedSize < initialSize) {  
                roundedSize <<= 1;  
            }  
        } else {  
            roundedSize = (initialSize + 7) / 8 * 8;  
        }  
  
        return roundedSize;  
    }  
  
    private static int computeInitialSampleSize(BitmapFactory.Options options,  
            int minSideLength, int maxNumOfPixels) {  
        double w = options.outWidth;  
        double h = options.outHeight;  
  
        int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math  
                .sqrt(w * h / maxNumOfPixels));  
        int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(  
                Math.floor(w / minSideLength), Math.floor(h / minSideLength));  
  
        if (upperBound < lowerBound) {  
            return lowerBound;  
        }  
  
        if ((maxNumOfPixels == -1) && (minSideLength == -1)) {  
            return 1;  
        } else if (minSideLength == -1) {  
            return lowerBound;  
        } else {  
            return upperBound;  
        }  
    } 
	public interface ImageCallback {
		public void imageLoaded(Bitmap bitmap);
	}
}
